/// <license>
/// Copyright (c) 2002-2008, DotNetNuke Corporation
/// All rights reserved
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
/// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
/// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
/// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
/// of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
/// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
/// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
/// DEALINGS IN THE SOFTWARE.
/// </license>

#region Using Statements

using System;
using System.Collections.Generic;
using System.Text;

using DotNetNuke.UI.WebControls;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Services.Search;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Web;
using DotNetNuke.Common;

#endregion

namespace DotNetNuke.Modules.Articles.Framework
{
    /// -----------------------------------------------------------------------------
    /// Namespace:  DotNetNuke.Modules.Articles.Framework
    /// Project:    Articles Private Assembly
    /// Class:      ArticlesController
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The ArticlesController Class handles common Business Layer function
    /// </summary>
    /// <history>
    /// 	[cnurse]	08/04/2006	Created
    /// </history>
    /// -----------------------------------------------------------------------------
    public class ArticlesController: ISearchable, IPortable
    {
        #region ISearchable Members

        public SearchItemInfoCollection GetSearchItems(ModuleInfo ModInfo)
        {
            SearchItemInfoCollection searchItems = new SearchItemInfoCollection();
            SearchItemInfo searchItem;

            foreach (ArticleInfo article in ArticleController.GetAllArticles(ModInfo.ModuleID))
            {
                //We will Index both the Article and the Abstract
                string content = HttpUtility.HtmlDecode(article.Body + " " + article.Abstract);

                //We will use the abstract as the description (unless it is null)
                string description = article.Abstract;
                if (String.IsNullOrEmpty(description))
                    description = article.Body;
                description = HtmlUtils.Shorten(HtmlUtils.Clean(HttpUtility.HtmlDecode(description), false), 100, "...");

                searchItem = new SearchItemInfo(ModInfo.ModuleTitle + " - " + article.Title, 
                                        description, article.CreatedByUser, article.CreatedDate, 
                                        ModInfo.ModuleID, article.ArticleId.ToString(), content, 
                                        "ArticleId=" + article.ArticleId.ToString(), 
                                        article.AbstractImage);
                
                searchItems.Add(searchItem);
            }

            return searchItems;
        }

        #endregion

        #region IPortable Members

        public string ExportModule(int moduleId)
        {
            //Create the Xml Document to hold the xml
            XmlDocument doc = new XmlDocument();
            XmlNode root = doc.AppendChild(doc.CreateElement("dnn_articles"));
            root.Attributes.Append(XmlUtils.CreateAttribute(doc, "version", "1.0.0"));

            //Get the Sections and serialize them
            XmlNode nodeSections = root.AppendChild(doc.CreateElement("sections"));
            SerializeSections(doc, nodeSections, moduleId, Null.NullInteger);

            //Get any Articles (that are not in a section) and serialize them
            XmlNode nodeArticles = root.AppendChild(doc.CreateElement("articles"));
            SerializeArticles(doc, nodeArticles, moduleId, Null.NullInteger);

            return doc.OuterXml;
        }

        public void ImportModule(int ModuleID, string Content, string Version, int UserID)
        {
            //Load the content into an XmlNode
            XmlNode root = Globals.GetContent(Content, "dnn_articles");

            foreach (XmlNode sectionNode in root.SelectNodes("sections/section"))
            {
                AddSection(sectionNode, Null.NullInteger, ModuleID, UserID);
            }

            foreach (XmlNode articleNode in root.SelectNodes("articles/article"))
            {
                AddArticle(articleNode, Null.NullInteger, ModuleID, UserID);
            }

        }

        #endregion

        private void AddArticle(XmlNode articleNode, int sectionId, int moduleId, int userId)
        {
            // Create an instance of the XmlSerializer specifying type and namespace.
            XmlSerializer serializer = new XmlSerializer(typeof(ArticleInfo));

            //Create an XmlReader for the xml to deserialize
            XmlReader reader = XmlReader.Create(new StringReader(articleNode.OuterXml));

            // Declare an object variable of the type to be deserialized.
            // Use the Deserialize method to restore the object's state.
            ArticleInfo article = (ArticleInfo)serializer.Deserialize(reader);
            article.ModuleId = moduleId;
            article.SectionId = sectionId;

            article.ArticleId = ArticleController.AddArticle(article, "Article Imported", userId);
        }

        private void AddSection(XmlNode sectionNode, int parentSectionId, int moduleId, int userId)
        {
            // Create an instance of the XmlSerializer specifying type and namespace.
            XmlSerializer serializer = new XmlSerializer(typeof(SectionInfo));

            //Create an XmlReader for the xml to deserialize
            XmlReader reader = XmlReader.Create(new StringReader(sectionNode.OuterXml));              
            
            // Declare an object variable of the type to be deserialized.
            // Use the Deserialize method to restore the object's state.
            SectionInfo section = (SectionInfo) serializer.Deserialize(reader);
            section.ModuleId = moduleId;
            section.ParentSectionId = parentSectionId;

            section.SectionId = SectionController.AddSection(section, userId);

            //Process the childsections
            foreach (XmlNode childSectionNode in sectionNode.SelectNodes("sections/section"))
            {
                AddSection(childSectionNode, section.SectionId, moduleId, userId);
            }

            //Process the articles
            foreach (XmlNode articleNode in sectionNode.SelectNodes("articles/article"))
            {
                AddArticle(articleNode, section.SectionId, moduleId, userId);
            }
        }

        private void SerializeArticles(XmlDocument doc, XmlNode parentNode, int moduleId, int sectionId)
        {
            XmlDocument xmlArticles;
            XmlNode nodeArticle;
            StringWriter sw;
            XmlSerializer xserArticles = new XmlSerializer(typeof(ArticleInfo));
            foreach (ArticleInfo article in ArticleController.GetArticlesBySection(moduleId,sectionId))
            {
                sw = new StringWriter();
                xserArticles.Serialize(sw, article);

                xmlArticles = new XmlDocument();
                xmlArticles.LoadXml(sw.GetStringBuilder().ToString());
                nodeArticle = xmlArticles.SelectSingleNode("article");
                nodeArticle.Attributes.RemoveNamedItem("xmlns:xsd");
                nodeArticle.Attributes.RemoveNamedItem("xmlns:xsi");

                //Import nodeArticle
                parentNode.AppendChild(doc.ImportNode(nodeArticle, true));
            }
        }

        private void SerializeSections(XmlDocument doc, XmlNode parentNode, int moduleId, int sectionId)
        {
            XmlDocument xmlSections;
            XmlNode nodeSection;
            StringWriter sw;
            XmlSerializer xserSections = new XmlSerializer(typeof(SectionInfo));
            foreach (SectionInfo section in SectionController.GetSectionsByParentSection(moduleId, sectionId))
            {
                sw = new StringWriter();
                xserSections.Serialize(sw, section);

                xmlSections = new XmlDocument();
                xmlSections.LoadXml(sw.GetStringBuilder().ToString());
                nodeSection = xmlSections.SelectSingleNode("section");
                nodeSection.Attributes.RemoveNamedItem("xmlns:xsd");
                nodeSection.Attributes.RemoveNamedItem("xmlns:xsi");

                //Get any Child Sections and serialize them
                XmlNode nodeChildSections = nodeSection.AppendChild(xmlSections.CreateElement("sections"));
                SerializeSections(xmlSections, nodeChildSections, moduleId, section.SectionId);

                //Get any Child Articles and serialize them
                XmlNode nodeChildArticles = nodeSection.AppendChild(xmlSections.CreateElement("articles"));
                SerializeArticles(xmlSections, nodeChildArticles, moduleId, section.SectionId);

                //Import nodeSection
                parentNode.AppendChild(doc.ImportNode(nodeSection, true));


            }
        }

    }
}
